﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;

[RequireComponent(typeof(Camera))]
[ExecuteInEditMode]
public class BlurOutline : MonoBehaviour
{
    public Camera camera;
    public float blurScale = 0.1f;
    [Range(0,16)] public int iteration = 1;
    [Range(0,1)] public float alphaClip = 0.1f;
    public Renderer[] renderers;
    public Color outlineColor = Color.black;
    public Material colorMaterial = null;
    public Material outlineMaterial = null;
    CommandBuffer commandBuffer;
    RenderTexture renderTexture;

    private void Start() {
        if(camera == null)
            camera = Camera.main;

        commandBuffer = new CommandBuffer();
        commandBuffer.name = "render outline";
        renderTexture = RenderTexture.GetTemporary(Screen.width,Screen.height,0);
        commandBuffer.SetRenderTarget(renderTexture);
        commandBuffer.ClearRenderTarget(true,true,Color.clear);
        for(int i=0;i<renderers.Length;i++)
            commandBuffer.DrawRenderer(renderers[i], colorMaterial);
    }

    private void OnEnable() {
        if(renderTexture)
        {
            RenderTexture.ReleaseTemporary(renderTexture);
            renderTexture = null;
        }
        if (commandBuffer != null)
        {
            commandBuffer.Release();
            commandBuffer = null;
        }
    }

    void OnRenderImage(RenderTexture source, RenderTexture dest)
    {   
        // outline color
        colorMaterial.SetColor("_OutlineColor", outlineColor);
        Graphics.ExecuteCommandBuffer(commandBuffer);

        // blur 
        RenderTexture rt1 = RenderTexture.GetTemporary(source.width,source.height,0);
        RenderTexture rt2 = RenderTexture.GetTemporary(source.width,source.height,0);
        outlineMaterial.SetFloat("_BlurScale", blurScale);
        Graphics.Blit(renderTexture, rt1, outlineMaterial, 0);
        Graphics.Blit(renderTexture, rt2, outlineMaterial, 1);
        for (int level = 0; level < iteration; level++)
        {
            Graphics.Blit(rt1, rt2, outlineMaterial, 0);
            Graphics.Blit(rt2, rt1, outlineMaterial, 1);
        }

        // cut
        outlineMaterial.SetTexture("_ColorTex",renderTexture);
        Graphics.Blit(rt2, rt1, outlineMaterial, 2);

        // combine
        outlineMaterial.SetFloat("_AlphaClip",alphaClip);
        outlineMaterial.SetTexture("_BlurTex",rt1);
        Graphics.Blit(source, dest, outlineMaterial, 3);

        RenderTexture.ReleaseTemporary(rt1);
        RenderTexture.ReleaseTemporary(rt2);
    }
}
